#import "ALEventColumnViewController.h"
#import "NSObject+BlockObservation.h"
#import "ALElementColumnEntry.h"
#import "NSManagedObjectContext+SMRAdditions.h"


@interface ALColumnEntryPreviewItem : NSObject <QLPreviewItem> {
}

@property (nonatomic, copy) NSURL *URL;
@property (nonatomic, retain) SMRColumnEntry *columnEntry;
@property (readonly) NSURL *previewItemURL;
@property (readonly) NSString *previewItemTitle;

-(id)initWithEntry:(SMRColumnEntry *)theEntry withURL:(NSURL *)theURL;

@end

@implementation ALColumnEntryPreviewItem

@synthesize URL;
@synthesize columnEntry;

-(id)initWithEntry:(SMRColumnEntry *)theEntry withURL:(NSURL *)theURL {
	if (!(self = [super init]))
		return nil;
	[self setURL:theURL];
	[self setColumnEntry:theEntry];
	return self;
}

-(NSURL *)previewItemURL {
	return [self URL];
}

-(NSString *)previewItemTitle {
	return [[[self columnEntry] representedObject] label];
}

@end


#pragma mark Constants


#pragma mark -
@interface ALEventColumnViewController ()
@property (nonatomic, retain) NSArray *quickLookPreviewItems;
-(void)updatePreviewItems_;
-(void)stopEditing_;
@end


#pragma mark -
@implementation ALEventColumnViewController

@synthesize eventColumnView;
@synthesize quickLookPreviewItems;
@synthesize entryPrototype;
@synthesize textElementPrototype;
@synthesize wrappingTextElementPrototype;
@synthesize dateElementPrototype;
@synthesize ratingElementPrototype;
@synthesize attachmentElementPrototype;


-(void)awakeFromNib {
	AMBlockTask selectionTask = ^(id object, NSDictionary *change) {
		QLPreviewPanel *previewPanel = [QLPreviewPanel sharedPreviewPanel];
		if ([previewPanel currentController] != self)
			return;
		WriteCacheFilesForEntries([[self eventColumnView] selectedObjects]);
		[self updatePreviewItems_];
		[previewPanel reloadData];
	};
	[[self eventColumnView] addObserverForKeyPath:@"selectedEntries" task:selectionTask];
    
	NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
    [noteCenter addObserver:self selector:@selector(elementTypeDidChange:) name:ALElementTypeDidChangeNotification object:nil];
}


#pragma mark -
#pragma mark Notifications

-(void)elementTypeDidChange:(NSNotification *)note {
	SMRColumnEntry *changedEntry = [note object];
	if ([changedEntry columnView] != [self eventColumnView])
		return;
	SMRColumnEntry *parent = [changedEntry parentEntry];
	SMRColumnEntry *newEntry = [self columnEntryPrototypeForRepresentedObject:[changedEntry representedObject]];
	if (!newEntry)
		return;
	[parent replaceChildEntry:changedEntry withEntry:newEntry];
}


#pragma mark -
#pragma mark Column view delegate methods

-(BOOL)columnView:(SMRColumnView *)aColumnView insertText:(id)aString {
	if (![aString isEqualToString:@" "])
		return NO;
    
	if ([[[self eventColumnView] selectedEntries] count] == 0)
		NSBeep();
	else 
		[NSApp sendAction:@selector(toggleQuickLook:) to:nil from:self];
	return YES;
}

-(BOOL)columnView:(SMRColumnView *)aColumnView doCommandBySelector:(SEL)aSelector {
	if (aSelector == @selector(deleteBackward:)) {
		NSArray *selectedObjects = [aColumnView selectedObjects];
		[[self managedObjectContext] smrDeleteObjects:selectedObjects];
		return YES;
	}
	if (aSelector == @selector(insertNewline:)) {
		[self insertNewline:self];
		return YES;
	}
	if (aSelector != @selector(cancelOperation:))
		return NO;
	[self stopEditing_];
	return YES;
}

-(SMRColumnEntry *)columnView:(SMRColumnView *)aColumnView entryForRepresentedObject:(id)object {
	return [self columnEntryPrototypeForRepresentedObject:object];
}


#pragma mark -
#pragma mark Event handling

-(void)keyDown:(NSEvent *)theEvent {
	[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
}

-(void)cancelOperation:(id)sender {
	[self stopEditing_];
}

-(void)stopEditing_ {
	SMRColumnView *aColumnView = [self eventColumnView];
	[aColumnView stopEditing];
	[[aColumnView window] makeFirstResponder:aColumnView];
}

-(void)insertNewline:(id)sender {
	SMRColumnView *aColumnView = [self eventColumnView];
	NSArray *selectedEntries = [aColumnView selectedEntries];
	if ([selectedEntries count] != 1)
		NSBeep();
	else if ([aColumnView editingEntry] == [aColumnView selectedEntry]) 
		[self cancelOperation:self];
	else
		[aColumnView editEntry:[aColumnView selectedEntry] atPoint:NSZeroPoint];
}


#pragma mark -
#pragma mark Quick Look Controller

-(BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
	return YES;
}

-(void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
	WriteCacheFilesForEntries([[self eventColumnView] selectedObjects]);
	[self updatePreviewItems_];
	[panel setDataSource:self];
	[panel setDelegate:self];
}

-(void)endPreviewPanelControl:(QLPreviewPanel *)panel {
	ClearQuicklookCacheFiles();
}


#pragma mark -
#pragma mark Quick Look Datasource

-(NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
	return [[self quickLookPreviewItems] count];
}


-(id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
	return [[self quickLookPreviewItems] objectAtIndex:index];
}

-(void)updatePreviewItems_ {
	NSMutableArray *previewItemArray = [NSMutableArray array];
	NSArray *selectedEntries = [[self eventColumnView] selectedEntries];
	for (SMRColumnEntry *columnEntry in selectedEntries) {
		ALEntry *entry = [columnEntry representedObject];
		NSMutableArray *urls = [NSMutableArray arrayWithObject:CacheURLForEntry(entry)];
		[urls addObjectsFromArray:AttachmentURLsForEntry(entry)];
		for (NSURL *url in urls) {
			ALColumnEntryPreviewItem *previewItem = [[ALColumnEntryPreviewItem alloc] initWithEntry:columnEntry withURL:url];
			[previewItemArray addObject:previewItem];
		}
	}
	[self setQuickLookPreviewItems:previewItemArray];
}


#pragma mark -
#pragma mark Quick Look delegate

-(NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item {
	SMRColumnEntry *entry = [(ALColumnEntryPreviewItem *)item columnEntry];
	NSRect entryRect = [[self eventColumnView] rectForEntry:entry];
	NSRect entryRectBase = [[self eventColumnView] convertRectToBase:entryRect];
	NSRect entryRectScreen = entryRectBase;
	entryRectScreen.origin = [[[self eventColumnView] window] convertBaseToScreen:entryRectBase.origin];
	return entryRectScreen;
}


#pragma mark -
#pragma mark Prototypes

-(SMRColumnEntry *)columnEntryPrototypeForRepresentedObject:(id)representedObject {
    return nil;
}

@end
